<template>
  <div>
    <el-form :model="step" label-width="95px" label-position="right" size="mini">
      <el-form-item label="步骤描述">
        <el-input v-model="step.desc" />
      </el-form-item>
      <el-form-item v-if="step.conditionType !==3 && step.conditionType !== 5" label="步骤类型">
        <el-cascader v-model="selectedStep" style="width: 100%;" :options="stepOptions" :props="cascaderProps" placeholder="请选择步骤类型。试试搜索 断言" filterable @change="handleChange($event)" />
      </el-form-item>

      <div style="margin-bottom: 15px;">
        <!-- HTTP -->
        <div v-if="step.stepType === 11">
          <el-tabs v-model="activeName">
            <el-tab-pane label="Headers" name="Headers">
              <el-input v-model="step.extra1" type="textarea" :rows="17" style="width: 100%" />
            </el-tab-pane>
            <el-tab-pane label="cookies" name="cookies">
              <el-input v-model="step.extra4" type="textarea" :rows="17" style="width: 100%" />
            </el-tab-pane>
            <el-tab-pane label="URL Params" name="Params">
              <el-input v-model="step.extra2" type="textarea" :rows="17" style="width: 100%" />
            </el-tab-pane>
            <el-tab-pane label="Body" name="Body">
              <el-input v-model="step.extra3" type="textarea" :rows="17" style="width: 100%" />
            </el-tab-pane>
            <el-tab-pane label="断言" name="Assert">
              <el-input v-model="step.extra5" type="textarea" :rows="17" style="width: 100%" />
            </el-tab-pane>
          </el-tabs>
        </div>

        <!-- WebSocket -->
        <div v-if="step.stepType === 12">
          <el-row style="margin-right: 20px;">
            <el-col :span="6">
              <div class="grid-content bg-purple">
                <el-form-item label="通道">
                  <el-select v-model="step.extra4.channel" placeholder="请选择通道">
                    <el-option v-for="item in laneOptions" :key="item.value" :label="item.label" :value="item.value" />
                  </el-select>
                </el-form-item>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="grid-content bg-purple">
                <el-form-item label="">
                  <el-tooltip content="当此信令会引发服务器主动关闭 WebSocket 连接时，需勾选此选项，否则脚本会报错" placement="top" :open-delay="500">
                    <el-checkbox v-model="step.extra4.close">服务器关闭通道</el-checkbox>
                  </el-tooltip>
                </el-form-item>
              </div>
            </el-col>
            <!-- todo: 后续编辑步骤，改成 json tree 的方式，通过鼠标选择，而不像现在写一个 json 字符串的方式 -->
            <!--    <el-col :span="4" :offset="2"><div class="grid-content bg-purple"> -->
            <!--    <el-button v-if="false" type="primary" circle>切换布局</el-button>-->
            <!--    </div></el-col>-->
          </el-row>
          <el-tabs v-model="activeName">
            <el-tab-pane label="URL Params" name="Params">
              <el-input v-model="step.extra2" type="textarea" size="mini" :rows="17" style="width: 100%" />
            </el-tab-pane>
            <el-tab-pane label="Body" name="Body">
              <el-input v-model="step.extra3" type="textarea" size="mini" :rows="17" style="width: 100%" />
            </el-tab-pane>
            <el-tab-pane label="断言" name="Assert">
              <el-input v-model="step.extra5" type="textarea" size="mini" :rows="17" style="width: 100%" />
            </el-tab-pane>
            <el-tab-pane label="保存变量" name="SaveVariate">
              <el-input v-model="step.extra1" type="textarea" size="mini" :rows="17" style="width: 100%" />
            </el-tab-pane>
          </el-tabs>
        </div>

        <!-- DataBase -->
        <div v-if="step.stepType === 14">
          <el-form-item label="SQL">
            <el-input v-model="step.extra3" :rows="17" placeholder="请输入您想要执行的 SQL 语句" style="width: 100%" type="textarea" />
            <div style="text-align: right;">
              <el-link :underline="false" href="https://www.cnblogs.com/rslai/p/17685723.html" style="font-size:12px;" target="_blank" type="primary">填写说明</el-link>
            </div>
          </el-form-item>
        </div>

        <!-- SSH -->
        <div v-if="step.stepType === 15">
          <el-form-item label="执行命令">
            <el-input v-model="step.extra2" placeholder="请输入您想要在这台机器执行的命令，eg：ls " type="textarea" :rows="17" style="width: 100%" />
          </el-form-item>
        </div>

        <!-- 全局步骤间隔、等待、WebSocket 等待 -->
        <div v-if="step.stepType === 101 || step.stepType === 105 || step.stepType === 106">
          <el-form-item :label="step.stepType === 101 ? '步骤间隔 (秒)' : '等待 (秒)'">
            <el-input-number v-model="step.extra1" :step="5" :min="1" :max="1000" />
          </el-form-item>
        </div>

        <!-- 自定义脚本 -->
        <div v-if="step.stepType === 107">
          <el-form-item label="Language">
            <el-select v-model="step.extra2" placeholder="请选择脚本语言" @change="changeLanguage($event)">
              <el-option v-for="item in languageOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
          <el-form-item label="运行脚本">
            <div class="json-editor" style="border:solid 1px #dfe4ed;">
              <json-editor ref="runScriptEditor" v-model="step.extra1" :mode="step.extra2" />
            </div>
            <div style="text-align: right;">
              <el-link :underline="false" href="https://www.cnblogs.com/rslai/p/17685707.html" style="font-size:12px;" target="_blank" type="primary">填写说明</el-link>
            </div>
          </el-form-item>
        </div>

        <!-- 校验内容 -->
        <div v-if="step.stepType === 103">
          <el-form-item label="校验内容">
            <el-input v-model="step.extra1" placeholder="请输入校验内容,eg: {'code':200,'msg':'success'}" type="textarea" :rows="17" style="width: 100%" />
          </el-form-item>
        </div>

        <!-- 保存变量 -->
        <div v-if="step.stepType === 104">
          <el-form-item label="保存变量">
            <el-input v-model="step.extra1" placeholder="请输入保存内容,eg: {   &quot;name&quot;: &quot;aaa&quot; , &quot;value&quot;: &quot;$result.id&quot;  }" type="textarea" :rows="17" style="width: 100%" />
          </el-form-item>
        </div>

        <!-- 设置变量 -->
        <div v-if="step.stepType === 108">
          <el-form-item label="设置变量">
            <el-input v-model="step.extra1" placeholder="请输入设置内容,eg: {   &quot;name&quot;: &quot;aaa&quot; , &quot;value&quot;: &quot;${param:random(5)}&quot;  }" type="textarea" :rows="17" style="width: 100%" />
          </el-form-item>
        </div>
      </div>

      <div v-if="step.conditionType === 5">
        <el-form-item label="循环次数">
          <el-input-number v-model="step.extra1" :min="1" :step="1" />
        </el-form-item>
      </div>

      <el-form-item>
        <template slot="label">
          <span>逻辑处理</span>
          <el-popover placement="right-start" title="逻辑处理" :width="400" trigger="hover">
            <p>意为该测试步骤关联的逻辑处理</p>
            <div><strong style="color: #409EFF">if：</strong>该步骤无异常时，会执行子步骤</div>
            <div><strong style="color: #E6A23C">eles if：</strong>如果上一个if条件步骤有异常，则进入该逻辑判断，无异常时会执行子步骤</div>
            <div><strong style="color: #F56C6C">else：</strong>如果以上条件全失败，则执行子步骤</div>
            <div><strong style="color: #67C23A">while：</strong>如果条件无异常，则重复执行子步骤</div>
            <div><strong style="color: #409EFF">for：</strong>根据输入的循环次数，重复执行子步骤</div>
            <template #reference><i class="el-icon-question" style="margin-left: 3px;" /></template>
          </el-popover>
        </template>
        <el-select v-model="step.conditionType" placeholder="请选择逻辑条件" @change="selectCondition">
          <el-option v-for="item in conditionTypeOptions" :key="item.value" :label="item.name" :value="item.value" />
        </el-select>
      </el-form-item>

      <el-form-item v-if="step.conditionType===0" prop="errorHandlingType">
        <template slot="label">
          <span>异常处理</span>
          <el-popover placement="right-start" title="异常处理" :width="400" trigger="hover">
            <p>意为该测试步骤出现异常时的处理方案</p>
            <div><strong style="color: #409EFF">忽略：</strong>忽略异常并继续执行（逻辑处理时不抛出异常）</div>
            <div><strong style="color: #E6A23C">告警：</strong>标记警告并获取异常截图和异常堆栈，然后继续执行（逻辑处理时不抛出异常）</div>
            <div><strong style="color: #F56C6C">中断：</strong>标记失败并获取异常截图、异常堆栈和测试录像，然后中断执行（逻辑处理时抛出异常）</div>
            <template #reference><i class="el-icon-question" style="margin-left: 3px;" /></template>
          </el-popover>
        </template>
        <el-select v-model="step.errorHandlingType" placeholder="请选择异常处理">
          <el-option v-for="item in errorOptions" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>

      <div style="text-align: center;">
        <el-button size="small" type="primary" @click="summitStep()">确认</el-button>
      </div>
    </el-form>
  </div>
</template>
<style lang="scss" scoped>
.json-editor {
  text-align-last: left;
  // width: 100%;
  // height: 100%;
  position: relative;

  ::v-deep {
    .CodeMirror {
      height: auto;
      min-height: 300px;
    }

    .CodeMirror-scroll {
      min-height: 300px;
    }

    .cm-s-rubyblue span.cm-string {
      color: #F08047;
    }
  }
}
</style>

<script>
import { conditionTypeOptions } from '@/enum/conditionType'
import { selectById as apiSelectById } from '@/api/functional_test/test_data_manage/api'
import JsonEditor from '@/components/JsonEditor'

export default {
  components: { JsonEditor },
  props: {
    stepIndex: {
      type: Number,
      default: undefined
    },
    step: {
      type: Object,
      default: null
    },
    stepOptions: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      conditionTypeOptions,
      activeName: 'Body',
      cascaderProps: {
        value: 'key',
        label: 'name',
        children: 'children',
        expandTrigger: 'hover'
      },
      selectedStep: [], // 选中的步骤
      errorOptions: [ // 异常处理类型 options
        {
          value: 1,
          label: '忽略'
        }, {
          value: 2,
          label: '警告'
        }, {
          value: 3,
          label: '中断'
        }
      ],
      laneOptions: [ // 通道 options
        {
          value: 'A',
          label: '通道 A'
        }, {
          value: 'B',
          label: '通道 B'
        }, {
          value: 'C',
          label: '通道 C'
        }, {
          value: 'D',
          label: '通道 D'
        }, {
          value: 'E',
          label: '通道 E'
        }, {
          value: 'F',
          label: '通道 F'
        }, {
          value: 'G',
          label: '通道 G'
        }, {
          value: 'H',
          label: '通道 H'
        }, {
          value: 'I',
          label: '通道 I'
        }, {
          value: 'J',
          label: '通道 J'
        }
      ],
      languageOptions: [ // 语言 options
        {
          value: 'groovy',
          label: 'Groovy'
        }, {
          value: 'python',
          label: 'Python'
        }, {
          value: 'javascript',
          label: 'JavaScript'
        }
      ],
      groovyDefault: 'def test() {\n' +
        '    def String responseBody = response.getBody()\n' +
        '    println "上一步执行结果：" + responseBody\n' +
        '    println "全局参数：" + globalParas\n' +
        '    "返回结果......"\n' +
        '}\n' +
        '\n' +
        'test()',
      pythonDefault: '#coding=utf-8\n' +
        'import sys\n' +
        'import os\n' +
        '\n' +
        "if __name__ == '__main__':\n" +
        '    response = sys.argv[1:][0]\n' +
        '    globalParas = sys.argv[1:][1]\n' +
        '    print("上一步执行结果：" + response)\n' +
        '    print("全局参数：" + globalParas)\n',
      javascriptDefault: 'var main = function() {\n' +
        '  var responseBody = response.getBody();\n' +
        '  print("上一步执行结果：" + responseBody);\n' +
        '  print("全局参数：" + globalParas);\n' +
        '  var value = globalParas.get("key");\n' +
        '  print("从全局参数中取得变量内容：" + value);\n' +
        '  \n' +
        '  return "返回结果......";\n' +
        '};'
    }
  },
  created() {
    this.selectedStep = this.findApiId(this.step, this.step.apiId)
  },
  methods: {
    // 查找 接口（api）id
    findApiId(row, id) {
      for (const item of this.stepOptions) {
        if ((-row.stepType) === item.id) {
          if (row.stepType <= 100) { // type 小于 100，表示是接口
            if (item.children) {
              const ret = this.recursionFindApiId(item.children, id)
              if (ret) {
                ret.unshift('t' + item.id) // 接口的第一层，要用 t- 开头，所以补 t
                return ret
              }
            }
          } else {
            return ['e-' + item.id] // 非接口的第一层，要用 e- 开头，所以补 e
          }
        }
      }
    },
    // 语言切换
    changeLanguage(value) {
      if (value === 'python') {
        this.$refs.runScriptEditor.setMode('text/x-python')
        this.$refs.runScriptEditor.setValue(this.pythonDefault)
      } else if (value === 'groovy') {
        this.$refs.runScriptEditor.setMode('text/x-groovy')
        this.$refs.runScriptEditor.setValue(this.groovyDefault)
      } else if (value === 'javascript') {
        this.$refs.runScriptEditor.setMode('text/javascript')
        this.$refs.runScriptEditor.setValue(this.javascriptDefault)
      }
    },
    // 递归查找 接口（api）id
    recursionFindApiId(apiList, id) {
      for (const api of apiList) {
        if (!api.isCatalog && api.id === id) {
          return ['e-' + api.id] // 元素要用 e- 开头，所以补上
        }
        if (api.children) {
          const ret = this.recursionFindApiId(api.children, id)
          if (ret) {
            ret.unshift('c-' + api.id) // 分类要用 c- 开头，所以补上
            return ret
          }
        }
      }
    },
    // 选中时触发，其中value值中包含id
    handleChange(event, index) {
      this.activeName = 'Body'
      if (event == null || event.length === 0) {
        return
      }
      if (event.length === 1) {
        this.step.apiId = event[0].substring(2) // 选择的是一级，apiId 就保存成 stepOptions 的 id。使用 substring 是要把 t-、c-、e- 去掉
      } else {
        this.step.apiId = Math.abs(event[event.length - 1].substring(2)) // 如果选择的是自定义接口，最后一个 event 内容就是 apiId。使用 substring 是要把 t-、c-、e- 去掉
      }
      this.step.stepType = Math.abs(event[0].substring(2)) // 使用 substring 是要把 t-、c-、e- 去掉
      this.step.extra4 = ''
      if (this.step.stepType <= 100) {
        apiSelectById(this.step.stepType, this.step.apiId).then(response => {
          if (this.step.stepType === 11 || this.step.stepType === 12) { // http 接口、WebSocket 接口
            for (const param of response.data.apiParams) {
              if (param.kind === 1) {
                this.step.extra1 = JSON.stringify(JSON.parse(param.example), null, 2)
              } else if (param.kind === 2) {
                this.step.extra2 = JSON.stringify(JSON.parse(param.example), null, 2)
              } else if (param.kind === 3) {
                this.step.extra3 = JSON.stringify(JSON.parse(param.example), null, 2)
              } else if (param.kind === 4) {
                this.step.extra4 = JSON.stringify(JSON.parse(param.example), null, 2)
              } else if (param.kind === 5) {
                this.step.extra5 = JSON.stringify(JSON.parse(param.example), null, 2)
              }
            }
            if (response.data.type === 12) { // 选择 WebSocket 接口后，通道默认为 A
              this.step.extra4 = { channel: 'A', close: false }
            }
          } else if (this.step.stepType === 15) { // SSH 接口
            const noneExtra = {}
            for (const param of response.data.apiParams) {
              noneExtra[param.name] = param.example
            }
            this.step.extra1 = JSON.stringify(noneExtra, null, 2)
            this.step.extra2 = ''
          }
        })
      } else if (this.step.stepType === 101 || (this.step.stepType === 105)) { // 步骤间隔
        this.step.extra1 = '10'
      } else if (this.step.stepType === 103 || this.step.stepType === 104 || this.step.stepType === 108) { // 断言或保存变量或设置变量
        this.step.extra1 = ''
      } else if (this.step.stepType === 107) { // 自定义脚本
        this.step.extra1 = this.groovyDefault
        this.step.extra2 = 'groovy'
      }
    },
    summitStep() {
      this.$emit('flush', this.stepIndex, this.step)
    },
    selectCondition(e) {
      if (!this.step.childSteps) { // 如果没有 childSteps 对象，初始化
        this.step.childSteps = []
      }
      this.step.errorHandlingType = 1
      this.selectedStep = [] // 选中的步骤
      if (e === 0) { // 如果 条件类型 选的是 无
        this.step.childSteps = []
        this.step.stepType = ''
      } else { // 如果选的不是 无，设置 stepType 为 30(条件类型)
        this.step.stepType = 30
      }
    }
  }
}
</script>
